perm filename CLASSE.TXT[CLS,LSP] blob sn#826006 filedate 1986-10-10 generic text, type T, neo UTF8







This draft document describes ideas now being discussed in a working group
whose goal is to define a standard for object-oriented programming in
Common Lisp.  This draft document was written by two members of the working
group, and represents our best efforts at a faithful transcript of
conclusions reached by the group to date.  Throughout this document we flag
some subjects as "still under discussion" or as possible extensions to the
standard.  This draft is not yet a complete or finished proposal for a
standard.

For the present, we are using the name "Classes" to refer to the new
standard.  It is important to have a name to use now, so we can clearly
distinguish between the new standard and the existing object-oriented
systems, such as Flavors and CommonLoops.  defclass is the mechanism for
defining new classes, so Classes seems a natural name for the tools and
ideas that comprise the object-oriented programming system.  Classes fits
nicely with other chapters of Common Lisp the Language, perhaps best placed
directly after the "Structures" chapter.

This draft document is in the public domain.








1.  STATEMENT OF GOALS


History and Motivation

There is currently substantial experience with object-oriented programming
paradigms within a variety of contexts. The two groups that have the most
experience in this area are Symbolics and Xerox.

Symbolics has experience with Flavors, an important object-oriented
programming extension to Lisp.  In 1985, Symbolics undertook a redesign of
Flavors, which resulted in New Flavors, a compatible extension to the
previous system.

Xerox has experience with object-oriented programming, both in Lisp and in
the Smalltalk tradition.  In 1985 Xerox began to design a new
object-oriented programming extension to Common Lisp, called CommonLoops.
CommonLoops and Flavors have important similarities.

Many people in the Common Lisp community now see a need for defining a
standard for object-oriented programming that would be part of Common Lisp.
The primary benefit of such a standard would be the ability to write
portable Common Lisp code in an object-oriented style.

At the Common Lisp committee meeting in Boston in December 1985, many
vendors of application software made it clear how important such a standard
is to them.  Again at the ACM Conference on Lisp and Functional Programming
in Cambridge in August 1986, the same point was made.

After the ACM Conference there was a meeting of the Common Lisp
Object-oriented Programming Committee.  A clear consensus was reached that
work should begin immediately to define a standard.  Representatives from
Xerox, Lucid, Symbolics, LMI, HP, Sun, and the Japanese CommonLisp
committee supported this consensus.

A working group composed of representatives from Xerox and Symbolics met
after the ACM Lisp Conference.  At that meeting we reached agreement on
several general goals:


                                     1








The standard will not be CommonLoops, nor will it be Flavors; however it
will incorporate the most useful features from both.  For example, it will
include multi-methods from CommonLoops and declarative method combination
from Flavors.

Goals for Classes

Some high-level goals were stated and agreed upon:

Sound basis
        Classes will include only those aspects of object-oriented
        programming that are well-understood at this time, and omit ideas
        that are still subjects for research.

Flexibility
        Classes will offer a flexible framework for designers to implement
        different schemes.  This encourages exploration of different styles
        of object-oriented programming.

Power   Classes will offer the basic tools for writing programs in an
        object-oriented style, and will be powerful enough to meet the
        needs of most programs.  Programmers need not write extensions to
        Classes to do straightforward object-oriented programming.

Compatibility
        It should be a convenient and simple procedure to translate
        programs written in CommonLoops or New Flavors to the new standard.
        We intend to provide tools that will perform the translation
        automatically.

Implementation
        Classes will allow efficient implementation on stock hardware as
        well as specialized machines.

Features to be Included in Classes

We intend to include the following features in Classes.  This is not an
exhaustive list, but is intended to communicate some of the areas of
agreement that have been reached.

                                     2








Generic functions
        Classes will use the normal Lisp function-calling syntax.

Class and Type Space Merging
        Every object in the Lisp system has a class and hence can be used
        to select methods.

Dispatching
        Classes will allow for several types of dispatching, including
        classical methods (which dispatch on a single object) and
        multi-methods (which dispatch on more than one object).

Multiple inheritance
        Classes can be combined together freely; they need not fit into a
        rigid hierarchy.

Meta-objects
        Classes defines objects for the major implementation entities of
        the system to allow for extensibility.  Classes, methods, and
        generic functions all have corresponding objects, organized by
        well-defined, documented protocols.

Declarative Method Combination
        Method selection and combination can be controlled declaratively.
        Users can define new method combination paradigms.















                                     3








2.  TERMINOLOGY


This section defines the terminology used in this document.

Object    Any Lisp datum, such as a number, a character, or an instance.

Class     An object that describes the structure and behavior of a set of
          objects.  All Lisp objects have a class, and can be queried for
          the class by using the class-of function.

Instance  Every object is an instance of some class.  The term instance is
          used to describe the instance/class relationship of an object to
          its class.

Metaclass Each object has a class.  A class itself is an object which has a
          class.  The metaclass of an object is the class of the class of
          the object.

          A metaclass itself is an object, which has a class.  The term
          metaclass is used to refer to a class that is suitable for being
          the class of a class.  An instance of a metaclass is a class.

Built-in class
          A built-in class corresponds to one of the predefined Common Lisp
          type specifiers; for example array is a built-in class for
          objects of type array.  The metaclass of an array is
          built-in-class.  You cannot define new built-in classes, nor use
          them in the definition of a new class.

Super-class
          The super-classes of a class are those classes that are included
          explicitly in the super-class list in the defclass form.  Each
          super-class is an integral part of a class.  The class inherits
          characteristics (such as slots) and behavior (such as methods)
          from each of its super-classes.  This is the primary mechanism
          for program modularity.  A typical mode of use is to define
          several basic classes and combine them to achieve specialized
          behavior.

                                     4








Components
          The components of a class include:  the class itself, the
          super-classes of the class, the super-classes of the
          super-classes of the class, and so on.

Slots     Slots define the structure of instances of the class, as do
          defstruct slots.  When defining a new class, you specify the
          slots of the class.  An :instance slot is a place where you can
          store data inside an instance.  This is the most commonly used
          kind of slot, where each instance has an individual slot of the
          same name.  A :class slot is a place where you can store data
          inside a class.  There is only one slot, whose value is shared by
          all instances of the class.

Accessor function
          A generic function that enables you to read the value of a slot.
          setf may be used with an accessor function to write the value of
          the slot.

Reader function
          A generic function that enables you to read the value of a slot.
          setf may not be used with a reader function.

Generic Function
          A function that has methods defined for it.  Ordinary functions
          have a single definition; generic functions have a distributed
          definition.  The implementation of an ordinary function is the
          same whenever the function is called.  The implementation of a
          generic function varies from call to call, depending on the
          classes of its arguments.

Method    An object that describes how to perform a generic function for a
          given set of arguments.  One or more methods are chosen according
          to the classes of the arguments to the generic function; the
          choosing of the method or methods is called dispatching.

Classical method
          The dispatching is based on the class of the first argument to
          the generic function (that is, on the class of a single object).

                                     5








Multi-method
          The dispatching is based on two or more arguments to the generic
          function (that is, on the class of several objects).

Default method
          A default method does not specify any type for discrimination
          purposes, or specifies the type as t.  A default method is
          selected when no more specific method for the generic function is
          defined.

SETF method
          A method for a setf generic function.  A setf generic function is
          the function that is called when you evaluate an expression such
          as:  (SETF (G ...) VALUE), where G is any generic function.  One
          example of G is a slot accessor.

























                                     6








3.  PROGRAMMER INTERFACE


This section describes the basic tools for defining classes, methods,
generic functions, and method combination types, and for making instances
of classes.  The conventions used here follow the rules described in Common
Lisp the Language, section 1.2.5.



3.1  Defining Classes


defclass enables you to invent a new class, which is a template of a new
data type with named slots.  defclass syntax allows for providing default
initialization of the slots, and for requesting that functions be
automatically generated to read and write the values of the slots, or to
construct new instances.

When you define a class you are also defining a type.  (typep object
class-name) is true if object is an instance of that class.

See the section "Motivation for Several DEFCLASS Defaults", page 45.

The syntax of defclass is:

(defclass class-name ({super-class-name}*) ({slot-spec}*)
  {option-name | (option-name {argument}*)}*)

For example:

(defclass ship ()
               (name
                (x-velocity :accessor ship-x-vel)
                (y-velocity :accessor ship-y-vel)
                (mass :reader ship-mass))
  :initable-slots
  (:default-init-plist :x-velocity 0 :y-velocity 0))


                                     7








class-name is a non-null symbol that names the class being defined.  If a
class is already defined with this name, this definition replaces the old
definition.

When the definition of a class changes, each existing instance of the class
is updated to the new format the next time it is accessed.  (Note that this
behavior might be categorized as an optional feature.)

Each slot-spec is one of:

slot-name       a non-null symbol.

(slot-name default-value)
                default-value is any form.  When an instance is made and no
                initial value for this slot is provided as an argument to
                make-instance, the slot is initialized to the value of this
                form.  The default-value is evaluated every time it is
                used.

(slot-name {slot-option-name slot-option-value}*)
                 The defined slot-option-names and their values are:

                :default-value form
                     This an alternate way for providing a default initial
                     value form.  The form is evaluated every time it is
                     used.

                :accessor generic-function-name
                     Specifies that a method for a generic function named
                     generic-function-name be automatically generated, to
                     read the value of this slot.  setf may be used with
                     generic-function-name to write the value of the slot.
                     generic-function-name must be a non-nil symbol.

                :reader generic-function-name
                     Specifies that a method for a generic function named
                     generic-function-name be automatically generated, to
                     read the value of this slot.  Note that setf may not
                     be used with generic-function-name to write the value

                                     8








                     of this slot.  generic-function-name must be a non-nil
                     symbol.

                :initable keyword
                     Specifies a keyword to be used to specify an initial
                     value of this slot, when a new instance is being made.
                     keyword must be a non-nil symbol.

                :allocation keyword
                     Specifies where storage is allocated for this slot.
                     The keyword can be one of these:

                     :instance
                          Storage is allocated in the instance itself; each
                          instance has its separate value for this slot.
                          This is the default.

                     :class
                          Storage is allocated in the class.  Thus a single
                          value for this slot is shared by all instances.
                          The exact semantics of :class are still under
                          discussion.  For example, how are subclasses
                          handled?  Does each subclass have a separate copy
                          of this slot, or do all subclasses share the same
                          copy?

                     :dynamic
                          This option is still under discussion; it is not
                          yet clear whether it should be in the standard.
                          The purpose of this option is to specify:
                          Storage is allocated in the instance at the time
                          of the first use of the slot.  If the slot is
                          initialized with a keyword argument to
                          make-instance, the slot is allocated then.  If
                          the first access is a read, then storage is
                          allocated and the default value declared in the
                          defclass, if any, is stored in the slot and
                          returned.  If the first access is a setf, then
                          storage is allocated and the value is stored in

                                     9








                          the slot and returned.  This option allows
                          infrequently-used slots to take storage only when
                          necessary.

                     :none
                          No storage is to be allocated; the slot should
                          not exist in instances of this class.  This is
                          used to override inheritance of slots defined by
                          a super-class.

If no default value for a slot is specified either in the defclass or the
make-instance form, the initial value of the slot is undefined and it is an
error to reference it.  This is the same behavior as a defvar with no
initial value form.

Each super-class-name is a non-null symbol naming a class to be included as
an integral part of this class.  The class now being defined will inherit
characteristics (such as slots) and behavior (such as methods) from each of
its super-classes.  Each super-class-name must refer to a user-defined
class, not a "built-in" class.  A built-in class corresponds to one of the
predefined Common Lisp type specifiers; for example array is a built-in
class for objects of type array.

Each class has a "component classes tree" composed of all its
super-classes, and the super-classes of each of its super-classes, and so
on.  This tree is used to compute the class precedence list of the class.
See the section "Determining the Class Precedence List", page 36.

Note the following rules of defclass:

   - All the component classes of a class must be defined before it is
     permitted to make an instance of the class.

   - A class must be defined before it can be mentioned as an argument
     specifier in a defmethod.

   - All component classes of a class must be defined before it is
     permitted to evaluate or compile a with-slots that uses this
     class.

                                    10








Some implementations might add other options to defclass.  Therefore it is
required that all implementations signal an error if they observe an option
that is not implemented locally.

Each option-name is a keyword that names an option; the arguments depend on
the option.  The set of defined options and their arguments is:

(:accessor-prefix prefix {slot-name}*)
                Causes a generic function to be generated automatically for
                each indicated slot, or all slots if no slot-name is
                present.  Such a generic function is called an accessor; it
                is used to read the value of a slot and can be used with
                setf to write the value of a slot.  The name of each
                accessor is the prefix followed by slot-name.  prefix is a
                string or symbol.

(:reader-prefix prefix {slot-name}*)
                Causes a generic function to be generated automatically for
                each indicated slot, or all slots if no slot-name is
                present.  The generic function is called a reader; it is
                used only to read the value of the slot and cannot be used
                with setf to write the value of the slot.  The name of each
                reader is the prefix followed by slot-name.  prefix is a
                string or symbol.

(:default-init-plist {keyword argument}*)
                Sets up defaults that are used when making an instance.
                Each keyword must be a valid keyword argument to
                make-instance.  Each argument is a form that provides the
                default value for that keyword argument if it is not
                supplied.  The user can override the defaults in the
                :default-init-plist by providing keyword arguments to
                make-instance.  The arguments are evaluated every time they
                are used.

(:initable-slots {slot-name}*)
                Specifies that it is allowed to initialize each slot
                indicated by slot-name, or all slots if no slot-names are
                present.  The initialization can be done by providing the

                                    11








                keyword with the same name as the slot (followed by the
                slot's initial value) as an argument to make-instance, or
                by including the keyword and value in the
                :default-init-plist.

(:init-keywords {keyword}*)
                This option is still under discussion; it is not yet clear
                whether it should be in the standard.  The purpose of this
                option is to:  Specify that each given keyword is an
                allowed keyword argument to make-instance for this class.
                There is no need to provide this argument to make it
                possible to initialize slots; that is done with the
                :initable-slots option.  The :init-keywords option is used
                in conjunction with methods you have written for
                make-instance.  If a make-instance method accepts an
                argument, you must explicitly make it an allowed keyword
                argument to make-instance by using this option.

(:documentation string)
                Enables you to specify an arbitrary string as documentation
                for this class.  The form (documentation class-name
                'type) retrieves this string.

(:constructor function-name [lambda-list])
                Causes a constructor function to be generated
                automatically.  You can call that constructor to make a new
                instance of the class.  lambda-list describes what the
                arguments to the constructor will be.  The syntax of the
                :constructor option to defclass is the same as that of the
                defstruct :constructor option described in Common Lisp the
                Language.

(:metaclass class-name)
                Specifies that this class has a different implementation
                than the system-provided default.  If you have invented a
                new metaclass, this option is the mechanism for creating
                classes of that metaclass.  class-name is the name of a
                class that is capable of being the class of a class.


                                    12








It is valid to specify more than one accessor, reader, and keyword for
initialization, for a single slot.  This can happen when the :accessor slot
option is used to specify an accessor for a slot, and the :accessor-prefix
option is used to specify that all slots should have an accessor with the
supplied prefix.

If neither a reader nor an accessor is specified for a slot, the slot can
only be accessed by the function slot-value or with-slots using :direct t.

    See the section "Accessing Slots Inside a Method: WITH-SLOTS", page 19.
    See the section "Accessing Slots Directly: SLOT-VALUE", page 21.



3.2  Making a New Instance


make-instance is a generic function that makes and initializes a new
instance of a class.

(make-instance {class-name | class} {keyword argument}*)

The first argument must refer to a user-defined class.  make-instance
cannot be used to make an instance of a built-in class.

The allowed keyword arguments depend on the defclass form.  Any keyword
specified with the :initable, :initable-slots, or :init-keywords option is
allowed.

If a keyword and argument is given to make-instance, it overrides any
default specified for that keyword in the defclass form, such as the
:default-init-plist option, or a default value in a slot-spec.

Note that make-instance is a generic function for which you can write
methods.  You can write methods to run after the new instance is created
and initialized.  If a make-instance method accepts arguments, use the
:init-keywords option to make them allowed arguments to make-instance.
Otherwise use either (object &rest ignore) or (object &key
&allow-other-keys) as the lambda-list of the method.

                                    13








3.3  Defining Methods and SETF Methods


defmethod defines a method for performing a generic function, when the
arguments to the generic function cause this method to be selected.
defmethod-setf defines a method for performing a setter function.

See the section "Why DEFMETHOD Disallows Method Selection on Optional
Parameters", page 49.

defmethod offers a general syntax which is appropriate for multi-methods,
and a classical syntax which is convenient for methods that dispatch on a
single argument.  The classical syntax automatically makes the slots of the
first argument lexically available in the method.  Multi-methods can use
with-slots to make slots of one or more objects lexically available in the
method.

General syntax:
   (defmethod generic-function {option}*
              qualified-lambda-list
     {declaration | doc-string}*
     {form}*)

   (defmethod-setf generic-function {option}*
                   qualified-lambda-list
                   setf-lambda-list
     {declaration | doc-string}*
     {form}*)

Classical syntax:
   (defmethod (generic-function self-class {option}*)
              qualified-lambda-list
     {declaration | doc-string}*
     {form}*)

   (defmethod-setf (generic-function self-class {option}*)
                   qualified-lambda-list
                   setf-lambda-list
     {declaration | doc-string}*

                                    14








     {form}*)

The classical syntax is equivalent to the following expression in the
general syntax:

   (defmethod generic-function {option}*
              ((self self-class) . qualified-lambda-list)
     {declaration | doc-string}*
     (with-slots (self)
       {form}*))


The following examples illustrate the syntax of defmethod for different
types of methods, through the qualified-lambda-list} part of the
expression.

Multi-method, no options:     (defmethod foo ((a c1) (b c2)) ...
Multi-method with option:     (defmethod foo :before ((a c1) (b c2))...
Classical method, no options: (defmethod (foo c1) (b) ...
Classical method with option: (defmethod (foo c1 :before) (b) ...
Default method, no options:   (defmethod foo (a b) ...
Default method with option:   (defmethod foo :before (a b) ...

generic-function
                A symbol that names the generic function being specialized.

self-class      A symbol that names the class of the first argument.

option          A non-nil symbol or a number, used by method combination to
                identify the method.  For example, :before or :after.

lambda-list     A lambda list

qualified-lambda-list
                A lambda-list as defined in Common Lisp the Language, page
                60, possibly with some variables replaced by qualified-
                variables so that method selection uses that argument.  A
                qualified-variable is a list such as:  (variable-name
                type-specifier).  A qualified-variable may be used wherever

                                    15








                a lambda-list allows only a variable and not a list.  Only
                required parameters may be qualified.  Note that the
                qulaification on optional parameters is still under
                discussion.

type-specifier  type-specifier can be a user-defined class, or the name of
                a structure defined by defstruct if the :type option was
                not used, or a Common Lisp type specifier from the subset
                listed here:

                array               integer          rational
                bit-vector          list             readtable
                character           long-float       sequence
                compiled-function   null             short-float
                complex             number           single-float
                cons                package          string
                double-float        pathname         symbol
                float               random-state     t
                hash-table          ratio            vector


                Note that the use of t as a type-specifier defines a
                default method.  Such a method is selected only when no
                more specific method for the generic function is defined.

setf-lambda-list
                Same as qualified-lambda-list except that for now there can
                be only one parameter.  In other words, setf-lambda-list is
                a lambda-list containing exactly one required parameter,
                which may be type-qualified.  It is either (variable-name)
                or ((variable-name type-specifier)).









                                    16








3.4  Defining Generic Functions


defgeneric allows you to specify options and declarations that pertain to
the generic function as a whole.  It is still under discussion whether it
should be required that a defgeneric be evaluated before any methods are
defined, or whether defmethod should set up a generic function with default
options, if no defgeneric has been evaluated.

(defgeneric generic-function lambda-list
  {option | (option {argument}*)}*)

(defgeneric-setf generic-function lambda-list setf-lambda-list
  {option | (option {argument}*)}*)

generic-function is a non-null symbol naming the generic function.

lambda-list is an ordinary lambda-list except no &aux variables are
allowed.

setf-lambda-list is (variable-name).

Each option is a keyword that names an option (or a documentation string).
The arguments depend on the option.  The set of defined options and their
arguments is:

(:documentation string) | string
                Associates a documentation string with the generic
                function.  The form (documentation generic-function-name
                'function) retrieves this string.

(:method-combination name {argument}*)
                Indicates that the generic function uses the type of method
                combination named by name.  The arguments depend on the
                type of method combination.  The most common argument is
                one to specify the order of methods, which is either
                :most-specific-first or :most-specific-last.  The default
                method combination type is :daemon, with the
                :most-specific-first order.

                                    17








(declare {declaration}+)
                Declarations that apply to the whole function (as opposed
                to declarations of variables) are permitted.  The only
                declaration in this standard is optimize, which can have
                the value of speed or space.  This allows the user to
                control whether method selection is optimized for speed or
                space; it has no affect on individual methods.  Some
                implementations might support other declarations.  If an
                implementation notices a declaration that it does not
                support, it should follow the rules described on page 161
                of Common Lisp the Language.

(:argument-precedence-order {parameter-name}+)
                This option alters the default way of selecting methods.
                By default, all type-qualified arguments are considered
                from left to right; each type-qualified argument has
                precedence over those to its right.  When this option is
                used, each type-qualified argument should be included as a
                parameter-name, so the full precedence order is supplied.

(:interface {form}+)
                Defines a function that runs instead of the generic
                dispatch.  This is completely transparent to anyone calling
                the generic function.  Such a prologue function can be used
                to rearrange the arguments, to standardize the arguments
                before the methods see them, to default optional arguments,
                to do the shared non-generic portion of an operation, or
                for any other purpose.  Another use of this option is to
                extend a generic function so it can also be used for
                objects that are not instances of a built-in class.

                Inside the forms you can trigger the generic dispatch with
                (call-methods args...) or (apply-methods args...).
                apply-methods treats the last argument as a list of
                arguments just like apply.  call-methods and apply-methods
                are defined lexically only inside the :interface option.

(:method-arguments {form}+)
                You can use this option to specify that the methods accept

                                    18








                different arguments than does the generic function itself.
                By default, the methods receive the same arguments that are
                specified at the top of the defgeneric form.  The
                :method-arguments option is only meaningful in connection
                with the :inteface option.

(:generic-function-class class-name)
                Specifies that this generic function has a different
                implementation than the system-provided default.  If you
                have invented a new generic function class, this option is
                the mechanism for creating a generic function of the new
                class.  class-name is the name of a class that is capable
                of being the class of a generic function.

(:method-class class-name)
                This is used to specify that all methods for this generic
                function have a different implementation than the
                system-provided default.  If you have invented a new method
                class, this option is the mechanism for creating methods of
                the new class.  Once the defgeneric form with this option
                is evaluated or compiled, any methods you define with
                defmethod will be implemented in the class name specified
                here.  class-name is the name of a class that is capable of
                being the class of a method.

Some implementations might add other options to defgeneric.  Therefore it
is required that all implementations signal an error if they observe an
option that is not implemented locally.



3.5  Accessing Slots Inside a Method: WITH-SLOTS


with-slots sets up a context giving you lexical access to the slots of one
or more instances.  Alternatively, you can use the accessor functions
within the method to access slots.

(with-slots ({var-name | (var-name {keyword argument}*)}*)

                                    19








  {form}*)

If var-name is given alone, all slots of the instance can be accessed by
name.  It is necessary that the class of the instance can be determined, so
var-name must be the name of a qualified parameter in the lambda-list of a
method lexically containing this with-slots form.  If the class of the
instance cannot be determined that way, use the :class option.

If more than one var-name is given, then they must have disjoint sets of
names for slots to avoid ambiguity of reference, or use the :prefix option
to distinguish between the names.  If any ambiguity is detected, with-slots
signals an error.

The recognized keywords and their arguments are:

:class class-name
                The class, or a super class, of the instance.  This option
                is necessary if the class of the instance cannot be
                determined from the method's lambda-list.

:prefix prefix  prefix is either a symbol or a string.  You can then
                reference a slot by the variable named by prefix followed
                by the slot name.  This enables you to keep separate two
                instances whose slot names overlap, such as when you want
                to access two instances of the same class, or that share a
                super-class.

:direct boolean If t, with-slots accesses the slots directly, using
                slot-value.  If nil, with-slots calls the accessor
                functions, which might invoke methods.

For example:

(defclass point ((x 0) (y 0)) ()
  (:accessors-with-prefix point-))

(defmethod move ((p point) dx dy)
  (with-slots (p)  ;; p is known as a point from the method args
    (setq x (+ x dx) y (+ y dy))))

                                    20









(defmethod move ((p point) dx dy)
  (with-slots ((p :direct t))
    (setq x (+ x dx) y (+ y dy))))

(defmethod make-same-height ((p1 point) (p2 point))
;;; set the y coord of p1 to the y of p2, its reference.
;;; slots of p1 are accessed using the slot names
;;; slots of p2 are accessed using ref-<slot-name>
  (with-slots (p1 (p2 :prefix ref-))
    (setq y ref-y)))

(defmethod make-horizontal ((l line))
   (let ((left (left-point l)) (right (right-point l)))
     (with-slots ((left  :class point :prefix left-)
                  (right :class point :prefix right-))
       (setq left-y right-y))))



3.6  Accessing Slots Directly: SLOT-VALUE


The usual way to access slots is to specify the :accessor or :reader option
to defclass and use the automatically-generated generic function.  However,
when no reader or accessor is defined for a slot, you can use slot-value to
access the slot.  setf may be used with slot-value to write the value of
the slot.  This is often useful in the debugging phase; it is also used
internally.

(slot-value instance symbol [no-error-p])

instance is the instance to be examined, and symbol is the slot name.  If
there is no such slot, an error is signalled, unless no-error-p is non-nil,
in which case nil is returned.





                                    21








3.7  CALL-NEXT-METHOD


call-next-method is used within the body of a method.  It is called with no
arguments.

The type of method combination in use determines which kinds of methods
allow call-next-method to be used.  The default method combination type,
:daemon, allows call-next-method to be used inside primary methods and
:around methods.  If you define a new type of method combination using the
simple form of define-method-combination, call-next-method can be done in
:around methods only.

(call-next-method) calls the next method with the same arguments that this
method received.  For the precise definition of "next method":  See the
section "Method Selection", page 40.  The value or values returned by that
method are returned by the (call-next-method) form.  Further computation
after call-next-method returns is possible, so this provides a general
imperative form of method-combination.

The exact definition of "same arguments" is still under discussion and must
be clarified.  This is particularly complicated in the face of optional,
rest, and keyword parameters.  call-next-method passes the actual values of
the parameter variables to the next method, except for keyword parameters,
which are passed via a rest-argument, not individually.  Thus defaulted
optional parameters cannot be defaulted again by the next method, but
keyword parameters can be re-defaulted by the next method.  If a parameter
variable is setq'ed, or another variable with the same name is bound, the
variable value visible at the lexical position of the call-next-method form
is used.

If call-next-method runs out of methods, it signals an error.

Possible extensions:

(call-next-method {argument}*)
                When at least one argument is given, call-next-method
                supplies those arguments instead of the arguments that this
                method received.  There are a lot of applications for this.

                                    22








(apply-next-method {argument}+)
                This is like call-next-method except that it uses apply
                instead of funcall.  That is, the last argument is really a
                list of arguments.



3.8  CLASS-OF


(class-of object)

Returns the most specific class of which object is a member.  Every Lisp
object has a class.

See the section "Assigning Classes to a Subset of Common Lisp Types", page
46.



3.9  DESCRIBE


The existing describe function is required to be replaced by this generic
function.

(defgeneric describe (object))

Each implementation is required to replace its former implementation of
describe with one or more methods.  Exactly which classes have methods for
describe is not specified.

Users can also write methods for describe; these methods must conform to
the Common Lisp definition of describe in Common Lisp the Language.  A
user-defined class without a method for describe inherits an appropriate
system-defined method.




                                    23








3.10  PRINT-OBJECT


(defgeneric print-object (object stream))

print-object outputs the printed representation of the object onto the
stream.  print-object is called by the print system, and should not be
called by the user.  A user-defined class can have a method for
print-object that defines its printed representation.  If it has no method,
it inherits a system-defined method which produces a default
printed-representation, perhaps using a syntax such as #<...> that is not
understood by the reader.

Each print-object method must obey the print-control special variables as
documented in Common Lisp the Language pp. 370-373.  The specific details
are:

*print-escape*  Each method must implement this.

*print-pretty*  This can be ignored by most methods other than the one for
                lists.

*print-circle*  This is handled by the printer and can be ignored by
                methods.

*print-level*   The printer takes care of this automatically, provided that
                each method handles exactly one level of structure and
                calls write (or an equivalent function) recursively if
                there are more structural levels.  The printer's decision
                of whether an object has components, and therefore should
                not be printed when the printing depth is not less than
                *print-level*, is implementation-dependent.  In some
                implementations its print-object method is not called, in
                others the method is called and the determination that the
                object has components is based on what it tries to output
                to the stream.

*print-length*  Methods that produce output of indefinite length must obey
                this, but most methods other than the one for lists can
                ignore it.
                                    24








*print-base*, *print-radix*, *print-case*, *print-gensym*, and
*print-array* apply to specific types of objects and are handled by the
methods for those objects.

In general, the printer and the print-object methods should not rebind the
print-control variables as they recurse through the structure, but this is
necessarily implementation-dependent.

In some implementations the stream argument passed to a print-object method
is not the original stream, but is an intermediate stream that implements
part of the printer, so methods should not depend on the identity of this
stream.

All of the existing printing functions (write, prin1, print, princ, pprint,
write-to-string, prin1-to-string, princ-to-string, the format ~S and ~A
operations, and the format ~B, ~D, ~E, ~F, ~G, ~$, ~O, ~R, and ~X
operations when they encounter a non-numeric value) are required to be
changed to go through the print-object generic function.  Each
implementation is required to replace its former implementation of printing
with one or more print-object methods.  Exactly which classes have methods
for print-object is not specified; it would be valid for an implementation
to have one default method that is inherited by all system-defined classes.

References: See MIT AI Memo 816, December 1984, by Richard C. Waters for a
discussion of PP, one of the better designed Lisp printers.  It handles
*print-level* and *print-length* invisibly to the print-object methods.
See also the inconclusive discussion on printing, *print-level*, and
recursion on the Common-Lisp mailing list around 21 November 1985 for
additional background.



3.11  Defining New Types of Method Combination


This section describes the tools for defining new types of method
combination.  The key function is:

define-method-combination

                                    25








                Enables you to declare a new type of method combination.
                The simple syntax defines a type of method combination that
                calls all the methods, passing the values they return to a
                given function.  The extended syntax offers a rich
                declarative syntax.

The following tools are often used in define-method-combination forms:

call-component-method
                Produces a form that calls a component method.

call-component-methods
                Produces a form that invokes a function or special form.
                Each argument to that function is a call to one of the
                methods in the supplied list of methods.

multiple-value-prog2
                Like multiple-value-prog1 but returns all the values of the
                second form.

method-options  Extracts the method options portion of a method.


3.11.1  Simple Syntax of DEFINE-METHOD-COMBINATION


The simple syntax is recognized by the second argument, which is a symbol.

(define-method-combination name operator {keyword argument}*)

name is a non-null symbol, often a keyword, that is the name of the type of
method combination being defined.

operator names a function, macro, or special form.  This defines a new type
of method combination in which all the methods are called and their values
are passed to operator.  :around methods are supported in the types of
method combination defined by the simple syntax, and call-next-method can
be done in those :around methods.  However, call-next-method cannot be done
in a primary method that uses a method combination type defined by the
simple syntax.
                                    26








The valid keywords for the simple syntax are:

:pretty-name string
                This string defaults to the lower case version of the
                supplied name of the method combination type.

:single-argument-is-value boolean
                Default is nil.  This option is used to optimize for
                operators that return their argument if there is only a
                single argument, such as +, max, and and.  If t is supplied
                for this option, and only one method is available, the
                method is called directly; operator is not called.

Method combination types defined by the simple syntax use
:most-specific-first order.  However, you can override that by using the
defgeneric :method-combination option, and providing the argument
:most-specific-last after the name of the method combination type.


3.11.2  Extended Syntax of DEFINE-METHOD-COMBINATION


The extended syntax is recognized by the second argument, which is a lambda
list.

(define-method-combination name parameters ({method-pattern}*)
  {options}* {form}*)

name is a non-null symbol, often a keyword, that is the name of the type of
method combination being defined.

parameters resembles the parameter list of a defmacro; it is matched
against the parameters specified in the :method-combination option to
defgeneric.

method-patterns is a list of method pattern specifications.  Each method
pattern selects some subset of the available methods and binds a variable
to a list of the methods.  Two of the method patterns select only a single
method and bind the variable to the chosen method if a method is found and

                                    27








otherwise to nil.  The variables bound by method patterns are lexically
available while executing the forms.  See the section "Method-patterns
Option to DEFINE-METHOD-COMBINATION", page 30.

Each option is a list whose car is a keyword.  These can be inserted in
front of the body forms to select special options.  See the section
"Options Available in DEFINE-METHOD-COMBINATION", page 32.

The forms are evaluated to produce the body of a handler.  Thus the body
forms of define-method-combination resemble the body forms of defmacro.
Backquote is used in the same way.  The body forms of
define-method-combination usually produce a form that includes invocations
of call-component-method and/or call-component-methods.  These functions
hide the implementation-dependent details of the calling of component
methods.

The forms are permitted to setq the variables defined by the
method-patterns, if further filtering of the available methods is required,
beyond the filtering provided by the built-in filters of the
method-patterns mechanism.  It is rarely necessary to resort to this.  It
is assumed that the values of the variables defined by the method patterns
(after evaluating the body forms) reflect the actual methods that will be
called.

forms must not signal errors.


3.11.3  Examples of DEFINE-METHOD-COMBINATION


The examples in this section are presented as illustration of the
complicated syntax of define-method-combination.  Note that the :daemon
type definition here does not allow for :around methods.

This form defines the :daemon method-combination type:

(define-method-combination :daemon
                           (&optional (order ':most-specific-first))
           ;; select methods and bind them to variables

                                    28








           ((before "before" :every :most-specific-first (:before))
            ;; select primary method,
            ;; if none is present, select :default method
            (primary "primary" :first order () :default)
            (after "after" :every :most-specific-last (:after)))
  ;;return values from primary method
  `(multiple-value-prog2
     ,(call-component-methods before)
     ,(call-component-method primary)
     ,(call-component-methods after)))

This form defines the :two-pass method combination type:

(define-method-combination :two-pass
                           (&optional (order ':most-specific-first))
           ((first "first-pass" :every order () :default)
            (second "after" :every :most-specific-last (:after)))
  ;;return values from last primary method to run
  `(multiple-value-prog1
     ,(call-component-methods first)
     ,(call-component-methods second)))

This form defines the :inverse-list method combination type:

(define-method-combination :inverse-list ()       ;take no parameters
        ;; select methods of type :inverse-list or :default
        ((methods "inverse-list" :every :most-specific-first
                                 () (:inverse-list) :default))
  (:arglist ignore list)
  (:method-transformer
    ;; each method receives a single argument, regardless
    (:generic-method-arglist `(list-element)))

  `(let ((list ,list))
     ,@(loop for (method . rest) on methods
           collect (call-component-method method
                    :arglist `(,(first list)))
           when rest
             collect `(setq list (cdr list)))))

                                    29








3.11.4  Method-patterns Option to DEFINE-METHOD-COMBINATION


Each method-pattern is a list of the form:

    (variable printer filter order {pattern}*)

variable is a variable to be bound to the list of methods resulting from
the application of this method-pattern (or to a single method or nil, in
the case where filter is one of the symbols :first or :last).  Each pattern
selects some subset of the methods (multiple patterns are combined with
or).  The order specifies the ordering of this subset and the filter
specifies further pruning of it.

printer is a format control string for describing this method concisely.
format is given this string and the method options as arguments.

filter is not evaluated; the filter type cannot be variable at run time.
filter must be one of the following symbols:

:first          Selects the first method in the specified order (nil if
                there are no methods).

:last           Selects the last method in the specified order (nil if
                there are no methods).

:every          Selects all the methods.

:remove-duplicates
                Selects all of the methods, excluding any duplicate
                methods.  If duplicates are present, only the first method
                is selected.  Duplicate methods are detected by applying
                equal to their defmethod options.

Additional filter types might be added in the future.  You can also do your
own filtering in the body by using setq on a variable.

order is a form that must evaluate to :most-specific-first or
:most-specific-last.  Often it is simply one of those keywords, a

                                    30








self-evaluating constant.  Another common practice is for order to be one
of the variables in parameters.

Each pattern is a list or ().  A method matches the pattern if its options
in the defmethod form match the given pattern.  The pattern () matches
methods with no options; that is, primary methods.  If you do not specify
any patterns, a default pattern of () is assumed.  patterns may be dotted
lists.

Match is by equal, except that * matches anything.  Each * in a pattern
matches anything in that position of a method function spec.  Dotted *
might be useful for variable length.

You can intermix special symbols with the patterns.  The only such symbol
currently allowed is:

:default        If the other patterns find any methods, this is ignored.
                If no other methods are found, the methods matched by the
                pattern (:default) are selected.

method-patterns are considered sequentially in the order they are written.
The first method-pattern that matches a component method with its patterns
takes care of that method, either including it or rejecting it depending on
its filter and any :default processing specified.  Subsequent
method-patterns do not see that method.  This means you should put the most
general patterns last if more than one method-pattern clause could match
the same method.  The methods are expected to be called in the order the
method patterns are written.  If this is not so, you should include an
:order clause.  See the section "Options Available in DEFINE-METHOD-
COMBINATION", page 32.

Any methods not taken care of by any method patterns are extraneous, and
implementations should warn about them.

Here is an example of the method-patterns used by :case method combination
type:

((case-documentation "case-documentation" :first order (:case-documentation
 (which-operations "which-operations" :first order (:which-operations))

                                    31








 (otherwise "otherwise" :first order (:otherwise))
 (cases "case ~s" :remove-duplicates order (*)))


3.11.5  Options Available in DEFINE-METHOD-COMBINATION


The options to define-method-combination include:

(:arglist {arg}*)
       Specifies the argument list of the generic function. As the body
       forms are being executed, each variable in args is bound to a form
       that accesses the relevant argument when evaluated as part of the
       form returned by the body forms.  &optional and &rest are permitted
       in args.

       The :arglist option is useful when the action depends on the
       arguments (rather than simply passing the arguments on to the
       component methods), as in :case or :inverse-list method combination.
       See the section "Examples of DEFINE-METHOD-COMBINATION", page 28.

(:order {var}*)
       Specifies the order in which the component methods will be called,
       for the benefit of flavor examining tools.  Each of the vars must be
       a variable bound by one of the method-patterns.  Normally all of the
       vars bound by method-patterns would be included in the :order
       option, but this is not required.  If no order is specified, the
       default is to use the vars in the order in which the method-patterns
       are written.

(:method-transformer {clause}*) can make changes to the arguments and body
       of methods for generic functions that use this type of method
       combination, and can control the validation of the arguments in the
       defmethod against the arguments in the defgeneric.  Code in clauses
       receives arguments bound to the following variables, and also has
       the parameters of the define-method-combination available to it:

       method   The name of the method


                                    32








       method-combination
                The method-combination type

       method-arglist
                The arglist specified for the method

       method-body
                The body of the method, including declarations

       generic-method-arglist
                The arglist specified for methods in the defgeneric.

       Each clause consists of a keyword and a form evaluated to produce a
       replacement for a normal item.  The clauses are:

       :method-arglist
                Replaces the argument list specified in defmethod.

       :method-body
                Replaces the body specified in defmethod.

       :generic-method-arglist
                Replaces the argument list for methods specified in
                defgeneric.

       :inhibit-checking
                If non-nil, inhibits comparing method-arglist and
                generic-method-arglist for the wrong number of arguments.


3.11.6  CALL-COMPONENT-METHOD


(call-component-method method {keyword value}*)

Produces a form that calls method.  If no keyword arguments are given to
call-component-method, the method receives the same arguments that the
generic function received.  Additional internal arguments might be passed
to the method, but the user never needs to be concerned about these.

                                    33








The recognized keywords are :apply and :arglist.

The value of :arglist is a list of forms to be evaluated to supply the
arguments to the method, instead of simply passing through the arguments to
the generic function.

When :arglist and :apply are both supplied, :apply should be followed by t
or nil.  If :apply t is supplied, the method is called with apply instead
of funcall.  :apply nil causes the method to be called with funcall.

When :arglist is not supplied, the value following :apply is the argument
that should be given to apply when the method is called.  (Certain internal
arguments are also included in the apply form.)  For example:

    (call-component-method method :apply list)

Results in:

    (apply method :apply list)

In other words, the following two forms have the same effect:

    (call-component-method method :apply list)
    (call-component-method method :arglist (list list)
                                             :apply t)

If method is nil, call-component-method produces a form that returns nil
when evaluated.

For examples:  See the section "Examples of DEFINE-METHOD-COMBINATION",
page 28.


3.11.7  CALL-COMPONENT-METHODS


(call-component-methods ({method}*) [:operator operator])

Produces a form that invokes the function or special form named operator.

                                    34








operator defaults to progn.  Each argument or subform is a call to one of
the methods.


3.11.8  MULTIPLE-VALUE-PROG2


(multiple-value-prog2 {form}*)

Evaluates the forms and returns all the values of the second form.  This is
similar to multiple-value-prog1.


3.11.9  METHOD-OPTIONS


(method-options method)

method-options returns the method's options, which is the options argument
that was given in the defmethod form for this method, a list of symbols
and/or numbers, such as :before or :around.



















                                    35








4.  BASIC UNDERLYING MECHANISMS


This section describes some important underlying mechanisms, including the
determination of a class precedence list, the selection and sorting of
available methods, and the final process of combining those methods and
executing them.



4.1  Determining the Class Precedence List


The method selection process requires that a class precedence list be
computed, which is an ordering of all components of that class from most
specific to least specific.

In the simplest case, suppose the default method combination (:daemon with
:most-specific-first order) is used.  Suppose two components of the class
supply a primary method for the same generic function and no other methods
(such as :before, :after, or :around) are available.  The method selection
process must choose one of the two primary methods to run; the method
supplied by the most specific class in the class precedence list is chosen.
For other illustrations of how the method selection process depends on the
class precedence list:  See the section "Method Selection", page 40.

The defclass forms of a class and each of its super-classes set local
constraints on the ordering of classes.  When a class is built from
super-classes, all of the local constraints of the class and its
super-classes are taken into account, and an ordering is computed that
satisfies all of these constraints.  In other words, the defclass forms
specify partial orderings, which must be merged into one total ordering.

Three rules govern the ordering of classes:

   1. A class always precedes its own super-classes.

   2. The local ordering of super-classes within each defclass form is
      preserved.

                                    36








   3. Duplicate classes are eliminated from the ordering; if a class
      appears more than once, it is placed as close to the beginning
      of the ordering as possible, while still obeying the other
      rules.

The first step in merging the partial orderings is to construct a tree of
classes.  The root of the tree is the class for which we are computing a
class precedence list.  From that root, the class's super-classes are added
from left to right, as they appear in the defclass form.

The ordering is determined by walking through the tree in depth-first
left-to-right order, and adding each class to the ordering if it fits the
constraints of the three rules.  If the class can be placed next in the
ordering without transgressing one of the three rules, it is added.  If
adding it would transgress a rule, that class is skipped.  If the end of
the tree is reached and some classes have not yet been placed in the
ordered list, we walk through the tree again, continuing to apply the three
rules to the remaining classes and add them to the ordering.  In
complicated programs, it is conceivable that we could walk through the tree
several times.

If some classes cannot be ordered according to the rules, an error is
signalled to inform the user of the conflicting constraints.  An example of
this is given at the end of this section.

Example of A Tree Walk

Here is an example of determining a class precedence list.  The classes are
defined:

    (defclass pie (apple cinnamon) ())
    (defclass apple (fruit) ())
    (defclass cinnamon (spice) ())
    (defclass fruit (food) ())
    (defclass spice (food) ())
    (defclass food () ())

The tree of classes for pie is:


                                    37








                 pie
                /   \
            apple  cinnamon
             /         \
          fruit      spice
            /           \
          food         food

The list begins with pie.  We continue, adding apple and fruit.  So far,
the (incomplete) ordered list is:

    (pie apple fruit

The next class is food, but we cannot place it next in the ordering because
doing so would transgress the rule that a class always precedes its own
super-classes.  If placed next, food would precede spice, and we know that
spice must precede food.  Thus we skip food and continue through the tree.
Because food appears later in the tree, we pick it up then.  The ordering
is now complete:

    (pie apple fruit cinnamon spice food)

Several Possible Orderings

In many cases, the three rules define a single valid ordering of classes.
In other cases, several orderings are valid.  For example, suppose pie
class and its super-classes are defined as follows:

    (defclass pie (apple cinnamon) ())
    (defclass apple (fruit) ())
    (defclass cinnamon (spice) ())
    (defclass fruit () ())
    (defclass spice () ())

The tree-walk results in the ordering:

    (pie apple fruit cinnamon spice)

In fact, there are two additional valid orderings:

                                    38








    (pie apple cinnamon fruit spice)
    (pie apple cinnamon spice fruit)

A well-conceived program must not depend on any one of those orderings, but
should work equally well under any of them.  For example, if your program
depends on spice preceding fruit in the ordering for pie, you should make
that constraint explicit by including those two classes in the list of
super-classes in the defclass form for pie.

Conflicting Class Definitions

It is possible to write a set of class definitions that cannot be ordered
using the rules.  For example:

    (defclass new-class (fruit apple) ())
    (defclass apple (fruit) ())

fruit must precede apple because the local ordering of super-classes is
preserved.  apple must precede fruit because a class always precedes its
own super-classes.  When this situation occurs, an error is signalled when
the system tries to compute the class precedence list.  At that point you
can redefine one or more of the classes to resolve the problem, presumably
by changing the local order of super-classes to resolve the conflict.

Note the following example, which appears at first glance to be a
conflicting set of definitions:

    (defclass pie (apple cinnamon) ())
    (defclass pastry (cinnamon apple) ())

The ordering for pie is:

    (pie apple cinnamon)

The ordering for pastry is:

    (pie cinnamon apple)

There is no problem with the fact that apple precedes cinnamon in the

                                    39








ordering of the super-classes of pie, but not in the ordering for pastry.
However, you cannot build a new class that has both pie and pastry as
super-classes .



4.2  Method Selection


Each class inherits methods from its components.  That is, if a method is
defined for a component of a class, that method is automatically considered
to "be available" for this class.  Depending on the other methods that are
available and the type of method combination used, that method might or
might not ever be used for this class.

Before describing the general mechanism, we present a simple case.  Class A
has a single component, Class B. Both Class A and B supply a primary method
for the same generic function.  The generic function dispatches on only one
argument; these are classical methods.  In :daemon method combination, a
single primary method is chosen from the set of available methods.  When
the argument to the generic function is an instance of Class A, the set of
available methods includes both methods.  The method chosen is the method
that is written for the most specific class; that is the method for Class
A. 

The method for Class B is said to be "shadowed".  If the method definition
for Class A is removed, the method for Class B will be used for instances
of Class A. 

This behavior enables a more specific class to override methods inherited
from its components.  It also allows a class to use an inherited method,
but modify it somewhat.  For example, a class can inherit a primary method
for a generic function and also supply a :before or :after method.

The same principles apply for multi-methods.  The general algorithm for
method inheritance is:

1.  Select the set of available methods.


                                    40








Given a generic function and the arguments to it, the set of available
methods includes all methods for that generic function whose qualified
parameters match the arguments.  A qualified parameter matches its argument
if the class of the argument has the class in the qualifier as a component
class.

2.  Sort the methods into a precedence order.

Examine the arguments supplied to the generic function one at a time, from
left to right.  (The left-to-right precedence order is the default. It can
be changed by the :argument-precedence-order option to defgeneric.)  For
each argument to the generic function, compare the corresponding parameter
type specifier of the methods.  Any unqualified parameters have an implied
type specifier of t.

If the type specifiers are not equal, you can determine which method has
precedence by the following rule:  Method X is more specific than method Y
if method X's parameter type specifier is earlier than method Y's parameter
type specifier in the class precedence list of the class of the argument.
t is implied at the very end of each class precedence list, so it is less
specific than any other class.

This algorithm is a function of the actual values of the arguments supplied
to the generic function, but in practice an implementation will not execute
the entire algorithm every time the generic function is called.  Most
implementations will normally precompute enough information that they can
make some quick tests on the classes of some of the arguments, perhaps
using hash tables, and get to the appropriate method as soon as possible.

Once the available methods are sorted into a precedence list, the type of
method combination decides which methods are to be executed, and what will
be done with their values.








                                    41








4.3  Method Combination


The default type of method combination is called :daemon.  This allows for
primary methods, and multiple :before and :after methods.  It also allows
for :around methods and call-next-method.

A method's type is determined by the option argument to defmethod.  The
following method types are recognized by :daemon method combination:

primary         These methods have no options in the defmethod form.  They
                are the most common type of method.

:default        This type of method acts as a primary method if no other
                primary method is available.  If a primary method is
                available, :default methods are ignored.  (These are not to
                be confused with "default methods", which are methods that
                are not type-qualified, or are type-qualified with t as the
                type.)

:before         :before methods have the keyword :before as the defmethod
                option.  They are used to specify code that is to run
                before the primary method.

:after          :after methods have the keyword :after as the defmethod
                option.  They are used to specify code that is to run after
                the primary method.

:around         :around methods have the keyword :around as the defmethod
                option.  :around methods offer an advanced capability that
                is rarely needed by most programmers.  Inside the body of
                an :around method, the function call-next-method can be
                used to immediately call the "next method" (see below);
                when the next method returns, the :around method can
                execute more code, perhaps based on the returned value(s).

The semantics of :daemon method combination are:

   - If there are any :around methods, the most specific :around

                                    42








     method is executed, and supplies the value(s) of the generic
     functioon.

   - If an :around method uses call-next-method, the next most
     specific :around method is executed, if one is available.

   - If there are no :around methods at all, or if call-next-method is
     done by the least specific :around method, the other methods are
     executed in the following way:

        * All the :before methods are executed, in most-specific-first
          order.

        * The most specific primary method is executed, and supplies
          the value(s) of the generic function.  If it does
          call-next-method, the second most specific primary method is
          executed, and so on until there are no more primary methods.
          An error is signalled if call-next-method is used and there
          is no primary method available to call.

        * All the :after methods are executed in most-specific-last
          order.

Special Notes:

If there is at least one :before or :after method, but no primary method, a
primary method that ignores its arguments and returns nil is assumed.

It should be noted that all :around methods run before any primary methods
run.  Thus a less specific :around method runs before a more specific
primary method.  This behavior might seem to violate modularity principles.
:around methods are included in the specification because there is a
documented history of a need for such a feature.

This section has described the use of the default :daemon method
combination type, and the default order, which is :most-specific-first.
You can use the :method-combination option to defgeneric and supply an
argument of :most-specific-last to change the order of methods.
:most-specific-last reverses the order of the primary methods and reverses

                                    43








the order of the :around methods.  The order of the :before and :after
methods is not changed, and it is still the case that all of the :around
methods are executed before any primary methods.





































                                    44








5.  DESIGN RATIONALE


This section discusses the design rationale behind some issues, and
mentions possible extensions to the Classes standard.



5.1  Motivation for Several DEFCLASS Defaults


In designing defclass we followed the principle that the definer of a class
should be able to decide which parts of the class are strictly internal,
and which are intended as an external interface.  This design principle is
a guideline that encourages good data abstraction.

Therefore, all defclass options that make a slot visible (such that its
value could be read, written, or initialized) are turned off by default.
The definer of a class needs to make an explicit decision to make a slot
visible externally, by specifying one or more options.

Along the same lines, the :accessor-prefix and :reader-prefix options do
not have a default for the prefix.  This represents a departure from the
analogous defstruct :conc-name option, which does have a default behavior,
the name of the structure followed by a hyphen.

If the definer of the class uses the :accessor-prefix or :reader-prefix
option, the slots are part of the external interface.  There are several
reasonable conventions for naming slot accessors and readers.  The definer
of the class might choose "" as the prefix, or the name of the class, a
more general component, or the name of a protocol followed by a hyphen.
Since no single possibility is clearly better than the others, we provide
no default prefix and leave the decision to the definer of the class.







                                    45








5.2  Assigning Classes to a Subset of Common Lisp Types


Many of the predefined Common Lisp type specifiers have a class associated
with them.  For example, an array is of type array, and of class array.  A
class that corresponds to a predefined Common Lisp type specifier is called
a built-in class.

Every class has a corresponding type.  However, not all types have a
corresponding class.  This section presents the mapping of classes to types
and explains the rationale for excluding some types.

Users can write methods that dispatch on any primitive Lisp type that has a
corresponding class.  However, it is not allowed to make an instance of a
built-in class with make-instance, nor to include a built-in class as a
super-class of a class.

The difference between built-in classes and user-defined classes is in the
implementation of instances.  Instances of a built-in class are implemented
in a specialized way that does not permit subclassing.  In some
implementations some classes documented as built-in might in fact be
implemented as user-defined classes, but portable programs cannot assume
this.

A type-specifier in a qualified-variable in a defmethod lambda-list must be
a member of a limited subset of Common Lisp type-specifiers.  It would be
useful to extend this to the full generality of Common Lisp
type-specifiers, but this raises technical issues that are not yet
appropriate for standardization.  For example, deciding what to do when an
argument is an instance of two types, both of which have methods, but
neither is a subtype of the other.  Another issue is the question of the
reliability of subtypep in some implementations.  Dealing with not raises
yet another technical issue.  For more information, see Boolean Classes by
D. McAllester and R. Zabih, a paper presented at the 1986 ACM First Annual
Conference on Object-Oriented Programming Systems, Languages, and
Applications.

Currently acceptable type-specifiers must be symbols (no lists are
permitted) in one of the following four categories:

                                    46








1. t, the universal class.
2. The name of a user-defined class, defined with defclass.
3. The name of a structure, defined with defstruct without using :type.
4. One of the following built-in class names:


    array
    bit-vector          subclass of vector, array, sequence
    character
    compiled-function
    complex             subclass of number
    cons                subclass of list, sequence
    double-float        subclass of float, number
    float               subclass of number
    hash-table
    integer             subclass of rational, number
    list                subclass of sequence
    long-float          subclass of float, number
    null                subclass of symbol, list, sequence
    number
    package
    pathname
    random-state
    ratio               subclass of rational, number
    rational            subclass of number
    readtable
    sequence
    short-float         subclass of float, number
    single-float        subclass of float, number
    string              subclass of vector, array, sequence
    symbol
    vector              subclass of array, sequence


Converting a partial ordering to a total ordering for the sake of brevity,
classes are ranked here in order from most specific to most general:

          rational float number symbol list vector array sequence


                                    47








List of Types that have no Corresponding Class

The following types could have been allowed as classes, but we have
excluded them for the reasons shown:

   - Types too specific to be useful to put methods on:  bit, keyword,
     standard-char, string-char

   - The type implies an implementation, not behavior:  bignum,
     fixnum, simple-array, simple-bit-vector, simple-string,
     simple-vector

   - Specification of the type is too vague: common, function, stream

   - This is the same as (not cons), and we are not yet dealing with
     not:  atom

   - No object can be an instance of this type: nil

The following types are also excluded as classes:  add, member, mod, not,
or, satisfies, values.

Another way of looking at these choices is that a type is included only if
there is a function for making objects of this type, such as make-array.
bit, fixnum, and bignums are excluded because there are no separate
functions for making objects of those types.  function is excluded because
there is no function to make functions, but compiled-function is included
because the compile function exists.  stream is excluded because there is
no single function to make streams, and in fact many different types of
objects can be streams.  This line of reasoning is not watertight, but it's
a pretty good heuristic.

Individual implementations can extend this to allow other type-specifiers.
Also individual implementations can add additional subclass relationships
as long as they do not violate Common Lisp the Language pp.33-5.  For
example, readtable can be a subclass of array, and hence inherit methods
from array, in some implementations.  It is important that the subclass
relationships among built-in classes be identical with the subtype
relationships among their corresponding types, so that the class system is
merged seamlessly with the type system.
                                    48








5.3  Why DEFMETHOD Disallows Method Selection on Optional Parameters


Currently defmethod only allows required parameters to have qualifiers and
be used for method selection.  It would be useful to extend defmethod to
allow optional and keyword parameters to be used for method selection.  (It
does not seem useful to allow rest, supplied-p, or auxiliary parameters to
be used for method selection.)  This extension has not been included in the
present standard because it raises technical issues about defaulting,
consistency among methods, and order of evaluation of initforms.
Discussion among the group has revealed that these issues are not well
enough understood yet to be appropriate for standardization.

Note that the effect of using an optional or keyword parameter for method
selection, from the point of view of the caller of the generic function,
can be achieved by using the :interface option to defgeneric to turn the
optional or keyword parameter of the generic function into a required
parameter of the methods.  Thus all defaulting and order of evaluation
issues are centralized within the defgeneric, at the cost of requiring the
writer of a method to specify a different parameter list.



5.4  Method Selection by Predications More General Than Classes


This section should be considered a possible extension to the standard.  It
is included in "Design Rationale" because it has been discussed in the
group.

The standard as currently proposed only allows method selection by the
classes of the arguments.  This could be extended in various ways.  It is
important that any extensions to method selection remain consistent with,
and a subset of, Common Lisp type-specifiers, rather than introducing a
whole new type system in parallel with the existing one.

Method selection could be extended to allow the full generality of Common
Lisp type-specifiers; that is, arbitrary predications.  The problem with
this is that there can be predications that have objects in common, but do

                                    49








not have a subtype/supertype relationship.  Thus if methods are defined for
both predications, it is not clear which method has precedence.  This is in
contrast to classes; if an object is an instance of two classes, one class
is always a component of the other, and the subtype/supertype relationship
can always be determined.

Rather than totally ruling out method selection by predications because it
might not be clear which method has precedence, predications could be
allowed, with the requirement that an error is signalled if such a method
ambiguity is actually encountered.  This would not prevent users from
defining a method on one predication, but would preclude defining methods
on two overlapping predications such as (integer 1 100) and (integer 50
144), which would signal an error if and only if the argument was an
integer between 50 and 100.

Subtype/supertype relationships can be computed for many of the most useful
predications, but in the most general case where this ordering is not
computable, the semantics are still well-defined, but not as amenable to
optimization.  At run-time the value of the argument must be tested against
both predications.  If both are true an error must be signalled, otherwise
the applicable method is well-defined.  This extra testing of predications
can be minimized by converting the type-specifiers to canonical form.  The
details are not given here because this is evidently an unexplored area
that is not yet appropriate for standardization.
















                                    50








6.  FUTURE DIRECTIONS


Our goal is to write a complete specification of the standard, which will
include all information necessary to implement Classes.  We invite feedback
on this initial draft from the community now, and will continue to invite
feedback as the specification process continues.

You can send comments on the ideas in this document to the mailing list:

               Common-Lisp-Classes-discussion@MC.LCS.MIT.EDU

You can request a copy of this document by sending a message to:

    Common-Lisp-Classes-document-request@Stony-Brook.SCRC.Symbolics.COM

As initially proposed, the standard was meant to fulfill two primary goals.
First, to define a basic set of tools for object-oriented programming.
Second, to define a flexible framework in which exploration of other
paradigms of object-oriented programming could take place.  These two goals
are conceptually distinct; the first addresses an immediate need, while the
second addresses a long-term strategy for continued experimentation toward
resolving some research areas.

Since the key ideas underlying the programming interface are already
well-understood and tested (in Flavors and CommonLoops), we expect that
this will be the quickest and simplest part of the standard to define.  We
hope to make a proposal for the programmer interface available as soon as
possible, in advance of the proposal for the flexible framework.  Users
could start writing programs in terms of the programmer interface sooner,
since they would not have to wait for the complete standard to be
finalized.

We intend to adapt the Meta-object protocol from CommonLoops for the
flexible framework, but it has neither been documented nor discussed within
the working group.  It is therefore premature to document the Meta-object
protocol at this time.

It is hoped that a portable implementation of Classes will be written, to

                                    51








allow the community to experiment with the new ideas and gain a deeper
understanding of Classes than would be possible by reading the
specification alone.





































                                    52








                                   INDEX







































                                    53








                             TABLE OF CONTENTS




                                                                       Page



1.  STATEMENT OF GOALS                                                    1



2.  TERMINOLOGY                                                           4



3.  PROGRAMMER INTERFACE                                                  7


    3.1  Defining Classes                                                 7
    3.2  Making a New Instance                                           13
    3.3  Defining Methods and SETF Methods                               14
    3.4  Defining Generic Functions                                      17
    3.5  Accessing Slots Inside a Method: WITH-SLOTS                     19
    3.6  Accessing Slots Directly: SLOT-VALUE                            21
    3.7  CALL-NEXT-METHOD                                                22
    3.8  CLASS-OF                                                        23
    3.9  DESCRIBE                                                        23
    3.10  PRINT-OBJECT                                                   24
    3.11  Defining New Types of Method Combination                       25
         3.11.1  Simple Syntax of DEFINE-METHOD-COMBINATION              26
         3.11.2  Extended Syntax of DEFINE-METHOD-COMBINATION            27
         3.11.3  Examples of DEFINE-METHOD-COMBINATION                   28
         3.11.4  Method-patterns Option to DEFINE-METHOD-COMBINATION     30
         3.11.5  Options Available in DEFINE-METHOD-COMBINATION          32
         3.11.6  CALL-COMPONENT-METHOD                                   33
         3.11.7  CALL-COMPONENT-METHODS                                  34


                                    iii








         3.11.8  MULTIPLE-VALUE-PROG2                                    35
         3.11.9  METHOD-OPTIONS                                          35



4.  BASIC UNDERLYING MECHANISMS                                          36


    4.1  Determining the Class Precedence List                           36
    4.2  Method Selection                                                40
    4.3  Method Combination                                              42



5.  DESIGN RATIONALE                                                     45


    5.1  Motivation for Several DEFCLASS Defaults                        45
    5.2  Assigning Classes to a Subset of Common Lisp Types              46
    5.3  Why DEFMETHOD Disallows Method Selection on Optional            49
         Parameters
    5.4  Method Selection by Predications More General Than Classes      49



6.  FUTURE DIRECTIONS                                                    51



INDEX                                                                    53










                                    iv